package model

import (
	"common/helper"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	g "github.com/doug-martin/goqu/v9"
	"github.com/doug-martin/goqu/v9/exp"
	"strconv"
	"time"
)

// 系统公告
type TblNotices struct {
	Id          string `db:"id" json:"id"`
	Title       string `db:"title" json:"title"`               //标题
	Content     string `db:"content" json:"content"`           //内容
	State       string `db:"state" json:"state"`               //0停用 1启用
	CreatedAt   uint32 `db:"created_at" json:"created_at"`     //创建时间
	CreatedUid  string `db:"created_uid" json:"created_uid"`   //创建人uid
	CreatedName string `db:"created_name" json:"created_name"` //创建人名
}

type NoticeData struct {
	D []TblNotices `json:"d"`
	T int64        `json:"total"`
	S uint         `json:"s"`
}

type noticeRawData struct {
	Status bool         `json:"status"`
	D      []TblNotices `json:"data"`
}

func noticeFlushCache() error {

	var record []TblNotices
	ex := g.Ex{
		"state": "1",
	}
	query, _, _ := dialect.From("tbl_notices").Select(colsNotice...).Where(ex).Order(g.C("created_at").Desc()).ToSQL()

	err := meta.MerchantDB.Select(&record, query)
	if err != nil {
		if err != sql.ErrNoRows {
			err = pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}
		return err
	}

	if len(record) == 0 {

		meta.MerchantRedis.Unlink(ctx, "notices").Err()
		return nil
	}

	for i, _ := range record {
		record[i].CreatedUid = ""
		record[i].CreatedName = ""
	}
	recs := noticeRawData{
		Status: true,
		D:      record,
	}

	b, err := json.Marshal(recs)
	if err != nil {

		return err
	}

	pipe := meta.MerchantRedis.Pipeline()
	defer pipe.Close()

	pipe.Del(ctx, "notices")
	pipe.Set(ctx, "notices", b, 0)
	pipe.Persist(ctx, "notices")
	pipe.Exec(ctx)

	return nil
}

// 公告添加
func NoticeInsert(data TblNotices) error {

	query, _, _ := dialect.Insert("tbl_notices").Rows(&data).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	noticeFlushCache()
	return nil
}

// 公告列表
func NoticeList(page, pageSize uint, startTime, endTime string, ex g.Ex) (NoticeData, error) {

	data := NoticeData{}

	if startTime != "" && endTime != "" {
		st, err := time.ParseInLocation("2006-01-02 15:04:05", startTime, time.Local)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		et, err := time.ParseInLocation("2006-01-02 15:04:05", endTime, time.Local)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		ex["created_at"] = g.Op{"between": exp.NewRangeVal(st.Unix(), et.Unix())}
	}

	t := dialect.From("tbl_notices")
	if page >= 1 {
		query, _, _ := t.Select(g.COUNT(1)).Where(ex).ToSQL()
		err := meta.MerchantDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}

	data.S = pageSize
	offset := (page - 1) * pageSize
	query, _, _ := t.Select(colsNotice...).Where(ex).Order(g.C("created_at").Desc()).Offset(offset).Limit(pageSize).ToSQL()
	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	return data, nil
}

// 公告 启用 停用
func NoticeUpdateState(id string, state int) error {

	data := TblNotices{}
	ex := g.Ex{
		"id": id,
	}
	query, _, _ := dialect.From("tbl_notices").Select(colsNotice...).Where(ex).ToSQL()
	err := meta.MerchantDB.Get(&data, query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	record := g.Record{
		"state": state,
	}
	query, _, _ = dialect.Update("tbl_notices").Set(record).Where(ex).ToSQL()
	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	noticeFlushCache()

	return nil
}

// 公告删除
func NoticeDelete(id string) error {

	ex := g.Ex{
		"id": id,
	}
	query, _, _ := dialect.Delete("tbl_notices").Where(ex).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	noticeFlushCache()
	return nil
}

// 公告更新
func NoticeUpdate(id string, record g.Record) error {

	ex := g.Ex{
		"id": id,
	}

	query, _, _ := dialect.Update("tbl_notices").Set(record).Where(ex).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	noticeFlushCache()

	return nil
}

type PopupWinItem struct {
	Id            uint   `json:"id,omitempty" db:"id" cbor:"id"`
	Nullity       string `json:"nullity" db:"nullity" cbor:"nullity"`
	FuncType      string `json:"func_type" db:"func_type" cbor:"func_type"`
	JumpType      string `json:"jump_type" db:"jump_type" cbor:"jump_type"`
	Sort          string `json:"sort" db:"sort" cbor:"sort"`
	AnnouTitle    string `json:"annou_title" db:"annou_title" cbor:"annou_title"`
	AnnouUrl      string `json:"annou_url" db:"annou_url" cbor:"annou_url"`
	AnnouShareUrl string `json:"annou_share_url" db:"annou_share_url" cbor:"annou_share_url"`
	AnnouPcUrl    string `json:"annou_pc_url" db:"annou_pc_url" cbor:"annou_pc_url"`
	Length        string `json:"length" db:"length" cbor:"length"` //长
	Width         string `json:"width" db:"width" cbor:"width"`    //宽
	Content       string `json:"content" db:"content" cbor:"content"`
}

type PopupWinItemAdd struct {
	Nullity       string `json:"nullity" db:"nullity" cbor:"nullity"`
	FuncType      string `json:"func_type" db:"func_type" cbor:"func_type"`
	JumpType      string `json:"jump_type" db:"jump_type" cbor:"jump_type"`
	Sort          string `json:"sort" db:"sort" cbor:"sort"`
	AnnouTitle    string `json:"annou_title" db:"annou_title" cbor:"annou_title"`
	AnnouUrl      string `json:"annou_url" db:"annou_url" cbor:"annou_url"`
	AnnouShareUrl string `json:"annou_share_url" db:"annou_share_url" cbor:"annou_share_url"`
	AnnouPcUrl    string `json:"annou_pc_url" db:"annou_pc_url" cbor:"annou_pc_url"`
	Length        string `json:"length" db:"length" cbor:"length"`
	Width         string `json:"width" db:"width" cbor:"width"`
	Content       string `json:"content" db:"content" cbor:"content"`
}

type PopupWinData struct {
	D []PopupWinItem `json:"d" cbor:"d"`
	T int64          `json:"total" cbor:"t"`
	S uint           `json:"s" cbor:"s"`
}

func GetPopupWinList(page, pagesize uint, ex g.Ex) (PopupWinData, error) {
	data := PopupWinData{}

	t := dialect.From("tbl_cfg_announcement")
	if page >= 1 {
		query, _, _ := t.Select(g.COUNT(1)).Where(ex).ToSQL()
		err := meta.MerchantDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}
		if data.T == 0 {
			return data, nil
		}
	}

	data.S = pagesize
	offset := (page - 1) * pagesize
	query, _, _ := t.Select("*").Where(ex).Order(g.C("sort").Desc()).Offset(offset).Limit(pagesize).ToSQL()
	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	return data, nil
}

func EditPopupWin(data PopupWinItem) error {
	if data.Id > 0 {
		query, _, _ := dialect.Update("tbl_cfg_announcement").Set(data).Where(g.Ex{"Id": data.Id}).ToSQL()
		_, err := meta.MerchantDB.Exec(query)
		if err != nil {
			return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}
		return nil
	} else {
		winedit := PopupWinItemAdd{
			Nullity:       data.Nullity,
			FuncType:      data.FuncType,
			JumpType:      data.JumpType,
			Sort:          data.Sort,
			AnnouTitle:    data.AnnouTitle,
			AnnouUrl:      data.AnnouUrl,
			AnnouShareUrl: data.AnnouShareUrl,
			AnnouPcUrl:    data.AnnouPcUrl,
			Width:         data.Width,
			Length:        data.Length,
			Content:       data.Content,
		}
		query, _, _ := dialect.Insert("tbl_cfg_announcement").Rows(winedit).ToSQL()
		_, err := meta.MerchantDB.Exec(query)
		if err != nil {
			return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}
		return nil
	}
}
func DeletePopupWin(id string) error {
	ex := g.Ex{
		"id": id,
	}
	query, _, _ := dialect.Delete("tbl_cfg_announcement").Where(ex).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	return nil
}

type SuspensionConfigData struct {
	D []SuspensionConfig `json:"d" cbor:"d"`
	T int                `json:"total" cbor:"t"`
}

// 配置
type SuspensionConfig struct {
	ID            int    `db:"id" json:"id"`
	Images        string `db:"images" json:"images"`
	PcImages      string `db:"pc_images" json:"pc_images"`
	JumpType      string `db:"jump_type" json:"jump_type"`
	Sort          string `db:"sort" json:"sort"`
	Status        string `db:"status" json:"status"`
	DisplayMethod string `db:"display_method" json:"display_method"`
	Url           string `db:"url" json:"url"`
	Length        string `db:"length" json:"length"`
	Width         string `db:"width" json:"width"`
	Title         string `db:"title" json:"title"`
}

func GetSuspensionList(param CommonParam) (SuspensionConfigData, error) {
	data := SuspensionConfigData{}
	where := "1=1"
	table := "tbl_cfg_suspension_images"
	join := ""
	oderBy := "sort"
	oderType := "asc"

	order := oderBy + " " + oderType

	offset := (param.Page - 1) * param.PageSize
	if param.Page >= 1 {
		count := "select count(1) from " + table + " as a where " + where

		err := meta.MerchantDB.Get(&data.T, count)
		if err != nil {

			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), count), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}
	field := "a.*"
	query := "select " + field + " from " + table + "  as a " + join + " where " + where + " order by " + order + " limit " + strconv.Itoa(param.PageSize) + " offset " + strconv.Itoa(offset)

	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil && err != sql.ErrNoRows {

		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	return data, nil
}

func UpdateSuspension(param SuspensionConfig, isDelete int8) error {
	table := "tbl_cfg_suspension_images"
	query := ""
	record := g.Record{
		"images":         param.Images,
		"pc_images":      param.PcImages,
		"url":            param.Url,
		"jump_type":      param.JumpType,
		"sort":           param.Sort,
		"status":         param.Status,
		"display_method": param.DisplayMethod,
		"length":         param.Length,
		"width":          param.Width,
		"title":          param.Title,
	}
	if param.ID > 0 {
		if isDelete == 0 {
			query, _, _ = dialect.Update(table).Set(record).Where(g.Ex{"id": param.ID}).ToSQL()
		} else {
			query, _, _ = dialect.Delete(table).Where(g.Ex{"id": param.ID}).ToSQL()
		}
	} else {
		query, _, _ = dialect.Insert(table).Rows(record).ToSQL()
	}

	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		fmt.Println(err)
		return errors.New("数据库错误")
	}
	return nil
}
